﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Threading;
using System.Threading.Tasks;

namespace Skyhook.AI.PathFinder
{
    static public class PathFinder
    {
        public delegate void OnPathRequestFinished();
        static int TargetX = 0;
        static int TargetY = 0;
        static BlockingMap Map = null;
        static PathRequestStorage PathStorage = new PathRequestStorage();
        static volatile bool IsWorking = false;
        static Task PathFindingTask = null;

        static PathFinder()
        {
            
        }
        static public void Initialize(BlockingMap map)
        {
            Map = map;
            PathFinderData.Initialize(map);
        }

        static public void Start()
        {
            IsWorking = true;
            PathFindingTask = new Task(ProcessPaths);
            PathFindingTask.Start();
        }
        static public void Stop()
        {
            IsWorking = false;
            PathFindingTask.Wait();
        }

        static void ProcessPaths()
        {
            while (IsWorking)
            {
                if (PathStorage.IsEmpty)
                {
                    Thread.Sleep(10);
                }
                else
                {
                    ProcessCurrentPath(PathStorage.TakeRequest());
                }
            }
        }

        static void ProcessCurrentPath(PathRequest request)
        {
            TargetX = request.TargetX;
            TargetY = request.TargetY;

            PathFinderData.Clear();

            PathFinderData.AddStartNode(request.StartX, request.StartY);
            PathFinderData.AddFinishNode(request.TargetX, request.TargetY);

            request.Path.Clear();

            if ((request.StartX == TargetX && request.StartY == TargetY) || Map.IsBlocked(TargetX, TargetY))
            {
                request.PathFound();
            }

            while (true)
            {
                if (PathFinderData.OpenNodesCount == 0)
                {
                    request.PathFound();
                    return;
                }
                if (PathFinderData.ProcessPoints() == true)
                {
                    //попали
                    PathFinderData.GetFinalPath(request.Path);
                    request.PathFound();
                    return;
                }
            }
        }

        static internal void FindPathAsync(int xstart, int ystart, int xfinish, int yfinish, MovePath path)
        {
            PathStorage.AddRequest(new PathRequest(xstart,ystart,xfinish,yfinish,path));
        }

        static internal void FindPathSync(int xstart, int ystart, int xfinish, int yfinish, MovePath path)
        {
            ProcessCurrentPath(new PathRequest(xstart, ystart, xfinish, yfinish, path));
        }
    }
}
